package com.inspur.edp.formserver.vmmanager.metaelement.service;

import com.inspur.edp.das.commonmodel.IGspCommonElement;
import com.inspur.edp.das.commonmodel.IGspCommonObject;
import com.inspur.edp.das.commonmodel.entity.GspCommonObject;
import com.inspur.edp.formserver.viewmodel.GspViewModel;
import com.inspur.edp.formserver.viewmodel.GspViewModelElement;
import com.inspur.edp.formserver.viewmodel.action.ViewModelAction;
import com.inspur.edp.formserver.viewmodel.collection.VMActionCollection;
import com.inspur.edp.formserver.viewmodel.exception.ViewModelException;
import com.inspur.edp.formserver.vmmanager.exception.VoManagerErrorCodes;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.lcm.metadata.spi.MetadataElementService;
import com.inspur.edp.lcm.metadata.spi.entity.MetadataDependencyDetail;
import com.inspur.edp.lcm.metadata.spi.entity.MetadataElement;
import com.inspur.edp.lcm.metadata.spi.entity.MetadataElementLocator;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;


/**
 * VO元数据发布前校验服务
 */
public class BffMetadataElementServiceImpl implements MetadataElementService {
    @Override
    public String getMetadataType() {
        return "GSPViewModel";
    }

    /**
     * 根据传入的MetadataElementLocator获取VO元数据的实体、字段、动作信息，
     *
     * @param metadata
     * @param set      VO字段Locator 表单调用时赋值
     *                 type：VoEelement 对应com.inspur.edp.lcm.metadata.spi.entity.MetadataElementLocator#getPath()
     *                 path:EntityID/ElementID 对应com.inspur.edp.lcm.metadata.spi.entity.MetadataElementLocator#getId()
     *                 <p>
     *                 VO实体对象Locator 表单调用时赋值
     *                 type:VoEntity 对应com.inspur.edp.lcm.metadata.spi.entity.MetadataElementLocator#getPath()
     *                 path: EntityID 对应com.inspur.edp.lcm.metadata.spi.entity.MetadataElementLocator#getId()
     *                 <p>
     *                 VO实体对象编号Locator Eapi调用时赋值
     *                 type:VoEntity-Code 对应com.inspur.edp.lcm.metadata.spi.entity.MetadataElementLocator#getPath()
     *                 path: childObjectCode1#childObjecCde2 对应com.inspur.edp.lcm.metadata.spi.entity.MetadataElementLocator#getId()
     *                 <p>
     *                 VO视图动作Locator Eapi、表单调用时赋值
     *                 type:VoAction 对应com.inspur.edp.lcm.metadata.spi.entity.MetadataElementLocator#getPath()
     *                 path:ActionID 对应com.inspur.edp.lcm.metadata.spi.entity.MetadataElementLocator#getId()
     * @return
     */
    public Map<MetadataElementLocator, MetadataElement> getMetadataElement(GspMetadata metadata, Set<MetadataElementLocator> set) {
        if (!(metadata.getContent() instanceof GspViewModel))
            return null;
        if (set == null || set.isEmpty())
            return null;
        GspViewModel viewModel = (GspViewModel) metadata.getContent();
        Map<MetadataElementLocator, MetadataElement> metadataElementMap = new HashMap<>();
        for (MetadataElementLocator metadataElementLocator : set) {
            buildMetaElement(viewModel, metadataElementLocator, metadataElementMap);
        }
        return metadataElementMap;
    }

    @Override
    public List<MetadataDependencyDetail> getMetadataDependencyDetails(GspMetadata gspMetadata) {
        return null;
    }

    private void buildMetaElement(GspViewModel viewModel, MetadataElementLocator metadataElementLocator, Map<MetadataElementLocator, MetadataElement> metadataElementMap) {
        switch (metadataElementLocator.getPath()) {
            case BffMetaElementConst.VO_ENTITY:
                buildEntityMetaElement(viewModel, metadataElementLocator, metadataElementMap);
                break;
            case BffMetaElementConst.VO_ENTITY_CODE:
                buildEntityMetaElementByCode(viewModel, metadataElementLocator, metadataElementMap);
                break;
            case BffMetaElementConst.VO_ELEMENT:
                buildVoElement(viewModel, metadataElementLocator, metadataElementMap);
                break;
            case BffMetaElementConst.VO_ACTION:
                buildAction(viewModel, metadataElementLocator, metadataElementMap);
                break;
            default:
                throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0037, null, metadataElementLocator.getPath());
        }
    }

    private void buildEntityMetaElementByCode(GspViewModel viewModel, MetadataElementLocator metadataElementLocator, Map<MetadataElementLocator, MetadataElement> metadataElementMap) {
        //节点对象编号
        String objectCode = metadataElementLocator.getId();
        if (objectCode == null || "".equals(objectCode))
            return;
        IGspCommonObject commonObject = getCommonObjectByCode(viewModel, objectCode);
        MetadataElement element = new MetadataElement();
        element.setType(metadataElementLocator.getId());
        element.setContent(commonObject);
        metadataElementMap.put(metadataElementLocator, element);
    }

    private IGspCommonObject getCommonObjectByCode(GspViewModel viewModel, String objectCode) {
        //Eapi请求中的子表信息带着 #,需要识别
        String[] codes = objectCode.split("#", 0);
        //获取最后一个子表
        String code = codes[codes.length - 1];
        return viewModel.getAllObjectList().stream().filter(item -> code.equals(item.getCode())).findFirst().orElse(null);
    }

    private void buildEntityMetaElement(GspViewModel viewModel, MetadataElementLocator metadataElementLocator, Map<MetadataElementLocator, MetadataElement> metadataElementMap) {
        String id = metadataElementLocator.getId();
        if (id == null || "".equals(id))
            return;
        IGspCommonObject commonObject = getCommonObject(viewModel, id);
        MetadataElement element = new MetadataElement();
        element.setType(metadataElementLocator.getPath());
        element.setContent(commonObject);
        metadataElementMap.put(metadataElementLocator, element);

    }

    private void buildVoElement(GspViewModel viewModel, MetadataElementLocator metadataElementLocator, Map<MetadataElementLocator, MetadataElement> metadataElementMap) {
        String voElementId = metadataElementLocator.getId();
        if (voElementId == null || "".equals(voElementId))
            return;
        //字段的传参path形式为：字段所在实体ID/字段ID
        String[] voElementPaths = voElementId.split("/", 0);
        if (voElementPaths.length < 2)
            return;
        String voEleBelongObjId = voElementPaths[0];
        String voEleId = voElementPaths[1];
        GspCommonObject commonObject = (GspCommonObject) getCommonObject(viewModel, voEleBelongObjId);
        GspViewModelElement commonElement = (GspViewModelElement) getCommonElement(commonObject, voEleId);
        MetadataElement element = new MetadataElement();
        element.setType(metadataElementLocator.getPath());
        element.setContent(commonElement);
        metadataElementMap.put(metadataElementLocator, element);
    }

    private void buildAction(GspViewModel viewModel, MetadataElementLocator metadataElementLocator, Map<MetadataElementLocator, MetadataElement> metadataElementMap) {
        String actionId = metadataElementLocator.getId();
        if (actionId == null || "".equals(actionId))
            return;
        ViewModelAction viewModelAction = getViewModelAction(viewModel, actionId);
        MetadataElement element = new MetadataElement();
        element.setType(metadataElementLocator.getPath());
        element.setContent(viewModelAction);
        metadataElementMap.put(metadataElementLocator, element);
    }

    private IGspCommonObject getCommonObject(GspViewModel model, String id) {
        IGspCommonObject objectById = model.findObjectById(id);
        return objectById;
    }

    private IGspCommonElement getCommonElement(IGspCommonObject commonObject, String voEleId) {
        if (commonObject == null)
            return null;
        GspViewModelElement element = (GspViewModelElement) commonObject.findElement(voEleId);
        return element;
    }

    private ViewModelAction getViewModelAction(GspViewModel model, String actionId) {
        VMActionCollection actions = model.getActions();
        ViewModelAction item = actions.getItem(actionId);
        return item;
    }
}
